# -*- coding: utf-8 -*-


"""
芷词 (LyricAngelica)
是一款免费开源的《我的世界》字幕|歌词处理工具
LyricAngelica (芷词)
A free open source tool used for dealing titles and lyrics for the use of _Minecraft_.

版权所有 © 2023 芷词 开发者
Copyright © 2023 all the developers of LyricAngelica

开源相关声明请见 仓库根目录下的 License.md
Terms & Conditions: License.md in the root directory
"""

# 芷词 开发交流群 861684859
# Email TriM-Organization@hotmail.com
# 若需转载或借鉴 许可声明请查看仓库根目录下的 License.md


# BUG退散！BUG退散！                    BUG退散！BUG退散！
# 异常、错误作乱之时                     異常、誤りが、困った時は
# 二六字组！万国码合！二六字组！万国码合！   グループ！コード＃！グループ！コード＃！
# 赶快呼叫 程序员！Let's Go！            直ぐに呼びましょプログラマ レッツゴー！

"""
版权所有 © 2023 睿乐组织 金羿("Eilles Wan") & 所有 芷词 开发者
Copyright © 2023 TriM-Organization EillesWan(W-YI_DoctorYI@outlook.com) and all the developers of LyricAngelica

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import os
import random
from typing import Dict, List, Literal, Tuple, Union

import chardet
from PIL import Image, ImageFont
from rich.progress import Progress

import LyricLib
from utils.ConsoleIO import format_ipt, ipt, isin, prt
from utils.McStructure import SingleCommand, commands_to_structure
from utils.Operations import get_text_Image_from_font_type

lyric_file = format_ipt(
    "LRC歌词文件地址：", os.path.isfile, "文件地址错误：{}；请重新输入。", strict_mode=True
)[0]

lrc = None

with open(lyric_file, "rb") as f:
    character_encoding_guess = chardet.detect(f.read())
if character_encoding_guess["confidence"] >= 0.75:
    if character_encoding_guess["encoding"]:
        if "gb" in (char_encoding := character_encoding_guess["encoding"]):
            char_encoding = "GB18030"
        else:
            char_encoding = character_encoding_guess["encoding"]

        lrc = LyricLib.Lyric.from_lrc(lrc_path=lyric_file, lrc_encoding=char_encoding)


if lrc is None:
    lrc = format_ipt(
        "无法判断文件编码，请手动输入：",
        lambda lrc_encode: LyricLib.Lyric.from_lrc(
            lrc_path=lyric_file, lrc_encoding=lrc_encode
        ),
        "输入有误：{}；请重新输入。",
    )[1]


pixel_per_block = 3
distance = 32
width_random_range = 50
height_random_range = 25

unifont_path = "./resources/unifont.ttf"
unifont_size = 16

particle_name = "minecraft:endrod"

scoreboard_name = "playtexts"

file_exact_name = os.path.splitext(os.path.split(lyric_file)[-1])[0]

unifont = ImageFont.truetype(unifont_path, unifont_size)


# prt(lrc)
whole_words = set()
for i in lrc.whole_contexts + " ":
    whole_words.add(i)

text_commands_table: Dict[str, List[Tuple[float, float]]] = {}
for i in whole_words:
    picture_bw = get_text_Image_from_font_type(i, unifont).convert("L")

    text_commands_table[i] = [
        (
            ((picture_bw.width / 2) - x) / pixel_per_block,
            ((picture_bw.height / 2) - y) / pixel_per_block,
        )
        for x in range(picture_bw.width)
        for y in range(picture_bw.height)
        if picture_bw.getpixel((x, y)) < 128
    ]
prt("已处理字词表")
# prt([(i, len(j)) for i, j in text_commands_table.items()])

# output_file = open(file_exact_name + ".mcfunction", "w", encoding="utf-8")

command_list: List[SingleCommand] = []
ms_previous = 0
command_amount = 0

previous_random_posx = previous_random_posy = 0

lyrics_list = sorted(lrc.lyrics.items(), key=lambda x: x[0].in_microseconds)

lyric_length_sub1 = len(lyrics_list) - 1

with Progress() as progress:
    total_task_start = progress.add_task(
        "[#0089F2 on #121110]正在处理歌词……", total=lyric_length_sub1
    )

    for i in range(lyric_length_sub1 + 1):
        time = lyrics_list[i][0]
        lyric = lyrics_list[i][1]

        this_microsec = (
            10000
            if i == lyric_length_sub1
            else (lyrics_list[i + 1][0].in_microseconds - time.in_microseconds)
        )

        this_microsec = (this_microsec) if this_microsec <= 10000 else 10000

        tick_delay = (
            round(this_microsec / (len(lyric.whole_context) - 1) / 50)
            if lyric.whole_context
            else 0
        )

        first_word = True

        for word in lyric.whole_context:
            now_delay = tick_delay
            while (
                (
                    posx_deviation := random.randint(
                        -width_random_range // 2, width_random_range // 2
                    )
                )
                - previous_random_posx
            ) ** 2 + (
                (
                    posy_deviation := random.randint(
                        -height_random_range // 2, height_random_range // 2
                    )
                )
                - previous_random_posy
            ) ** 2 < (
                unifont_size / pixel_per_block
            ) ** 2:
                # prt("NotSuitable Distance")
                pass
            previous_random_posx = posx_deviation
            previous_random_posy = posy_deviation
            for pos in text_commands_table[word]:
                command_list.append(
                    SingleCommand(
                        command="execute as @a at @s run particle {} ^{} ^{} ^{}".format(
                            particle_name,
                            pos[0] + posx_deviation,
                            pos[1] + posy_deviation,
                            distance,
                        ),
                        condition=False,
                        tick_delay=round((time.in_microseconds - ms_previous) / 43)
                        if first_word
                        else now_delay,
                        annotation="字 {} 在 {} 时".format(word, time.in_microseconds),
                    )
                )
                first_word = False
                now_delay = 0
                command_amount += 1
            progress.update(
                total_task_start,
                description="[#0089F2 on #121110]处理字 {}".format(word),
                advance=1 / len(lyric.whole_context),
            ),  # type: ignore

        ms_previous = time.in_microseconds + (
            tick_delay * (len(lyric.whole_context) - 1) * 50
        )

prt("指令转换完成，共 {} 条".format(command_amount))

struct, size, fn_pos = commands_to_structure(command_list, max_height=63)

with open(file_exact_name + ".mcstructure", "wb+") as f:
    struct.dump(f)

prt("大小：{} 末点：{}".format(size, fn_pos))

# output_file.close()
